#include "sqlconnpool.h"
using namespace std;

SqlConnPool::SqlConnPool() {
    useCount_ = 0;
    freeCount_ = 0;
}

SqlConnPool* SqlConnPool::Instance() {
    static SqlConnPool connPool;
    return &connPool;
}


//创建出mysql数据库连接,存到队列SqlConnPool.connQue_中
void SqlConnPool::Init(const char* host, int port,const char* user,const char* pwd, const char* dbName,
            int connSize = 10) {
  assert(connSize > 0);

  //默认创建10个mysql连接
  for (int i = 0; i < connSize; i++) {
    MYSQL *sql = nullptr;
    sql = mysql_init(sql);
    assert(sql);
    sql = mysql_real_connect(sql, host,user, pwd,dbName, port, nullptr, 0);
    assert(sql);
    mysql_set_character_set(sql,"utf8");//不设置,数据库里的中文mysql_fetch_row读出来是?
    connQue_.push(sql);
  }
  MAX_CONN_ = connSize;
  sem_init(&semId_, 0, MAX_CONN_);
}


//从队列头拿一个mysql连接
MYSQL* SqlConnPool::GetConn() {
  MYSQL *sql = nullptr;
  if(connQue_.empty()){
    LOG_WARN("SqlConnPool busy!");
    return nullptr;
  }
  //信号量的值大于0,则减少信号量的值并继续执行
  //信号量的值为0,则阻塞调用线程，直到有其他线程对信号量进行操作    
  sem_wait(&semId_);
  {
    //{}限定互斥锁的作用范围
    //防止多个线程同时对队列进行操作
    lock_guard<mutex> locker(mtx_);
    sql = connQue_.front();
    connQue_.pop();
  }
  return sql;
}

//将一个mysql连接放到队列尾
void SqlConnPool::FreeConn(MYSQL* sql) {
    assert(sql);
    lock_guard<mutex> locker(mtx_);
    //添加到队尾
    connQue_.push(sql);
    //将信号量 semId_ 的值加1
    sem_post(&semId_);
}

//关闭数据库连接池
//将队列中mysql连接都关掉,并将队列清空
void SqlConnPool::ClosePool() {
    lock_guard<mutex> locker(mtx_);
    while(!connQue_.empty()) {
        auto item = connQue_.front();
        connQue_.pop();
        mysql_close(item);
    }
    mysql_library_end();        
}

//得到数据库连接的数量
int SqlConnPool::GetFreeConnCount() {
    lock_guard<mutex> locker(mtx_);
    return connQue_.size();
}

SqlConnPool::~SqlConnPool() {
    ClosePool();
}
